<?php
/**
 * AMQP连接池
 */
declare(strict_types=1);

namespace Libraries\Connections;

use Swoole\ConnectionPool;
use Libraries\Connections\Drivers\Amqp;
use Libraries\Config;

class AmqpConn
{
    private static $arrPool = [];

    /**
     * 从连接池中取出一个
     * @param string $strName
     * @return Amqp|null
     */
    public static function get(string $strName = ''): ?Amqp
    {
        strlen($strName) || $strName = 'default';
        $objPool = self::init($strName, true);
        if (!$objPool) {
            return null;
        }
        for ($i = 3; $i--;) { // 3次尝试
            $objAmqp = $objPool->get();
            if ($objAmqp && $objAmqp->reConnect()) {
                return $objAmqp;
            }
            self::put(null, $strName);
        }
        return null;
    }

    /**
     * 归还一个连接
     * @param Amqp|null $objAmqp
     * @param string $strName
     * @return void
     */
    public static function put(?Amqp $objAmqp, string $strName = ''): void
    {
        strlen($strName) || $strName = 'default';
        $objPool = self::init($strName);
        $objPool && $objPool->put($objAmqp);
    }

    /**
     * 关闭所有的连接池
     * @param string $strName
     * @return void
     */
    public static function close(string $strName = ''): void
    {
        if (strlen($strName)) {
            $objPool = self::init($strName);
            $objPool && $objPool->close();
            unset(self::$arrPool[$strName]);
        } else {
            foreach (self::$arrPool as $strName => $objPool) {
                $objPool && $objPool->close();
                unset(self::$arrPool[$strName]);
            }
        }
    }

    /**
     * 取连接池
     * @param string $strName
     * @param bool $blnSetNx
     * @return ConnectionPool|null
     */
    private static function init(string $strName, bool $blnSetNx = false): ?ConnectionPool
    {
        if (isset(self::$arrPool[$strName])) {
            return self::$arrPool[$strName];
        }
        if (!$blnSetNx) {
            return null;
        }
        $intSize = 0;
        $arrConfig = Config::get('rabbitmq_' . $strName);
        $arrConfig || $arrConfig = Config::get('rabbitmq');
        if ($arrConfig) {
            $intSize = intval($arrConfig['pool_size'] ?? 5);
            unset($arrConfig['pool_size']);
        }
        if ($intSize > 0) {
            self::$arrPool[$strName] = new ConnectionPool(function () use ($arrConfig) {
                return new Amqp($arrConfig);
            }, $intSize);
            return self::$arrPool[$strName];
        }
        return null;
    }
}
